/*
 * (C) APUE
 * We may use sigsetjmp/siglongjmp in signal handler instead of setjmp/longjmp
 * Following will use the two methods to verify
 * Notes:
 * 	1.
 */

#include "apue.h"
#include <setjmp.h>
#include <time.h>

static void sig_usr1(int);
static void sig_alrm(int);

static sigjmp_buf jmpbuf;
/* static jmp_buf jmpbuf; */

static volatile sig_atomic_t canjump;

int main()
{
	/* set signal hander */
	if (signal(SIGUSR1, sig_usr1) == SIG_ERR)
		err_quit("signal(SIGUSR1) error");
	if (signal(SIGALRM, sig_alrm) == SIG_ERR)
		err_quit("signal(SIGALRM) error");

	/* print current signal mask set */
	pr_mask("starting main: ");

	/* global jump setting */
	if (sigsetjmp(jmpbuf, 1))
	{
		pr_mask("ending main: ");
		exit(0);
	}

	canjump = 1;	/* now sigsetjmp() is OK */

	while (1)
		pause();
}

static void sig_usr1(int signo)
{
	time_t starttime;
	if (canjump == 0)
		return; /* before sigsetjmp() is OK, ignore signals */

	pr_mask("starting sig_usr1: ");

	alarm(3);	/* SIGALRM in 3 seconds */

	starttime = time(NULL);
	while (1)
	{
		/* busy waiting for 5 seconds */
		if (time(NULL) > starttime + 6)
			break;
	}

	pr_mask("finishing sig_usr1: ");
	canjump = 0;
	siglongjmp(jmpbuf, 1);	/* jump back to main, not return */
}

static void sig_alrm(int signo)
{
	pr_mask("in sig_alrm: ");
}
